package com.lehecai.core.search.entity;

import com.lehecai.core.search.api.SearchApiRequestFilter;
import com.lehecai.core.search.api.SearchApiRequestFilterItem;
import com.lehecai.core.search.converter.ISearchEntityPropertyConverter;
import com.lehecai.core.search.entity.lottery.PlanOrderSearchDefine;
import com.lehecai.core.search.entity.member.RecordRechargeSearchDefine;
import com.lehecai.core.search.type.SearchEntityKey;
import com.lehecai.core.util.CoreJSONUtils;
import net.sf.json.JSONArray;
import org.apache.commons.beanutils.PropertyUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author hanwenda
 * 
 */
public class SearchEntityDefine {

	private final static Logger logger = LoggerFactory.getLogger(SearchEntityDefine.class.getName());

	private static Map<SearchEntityKey, SearchEntityPropertyDefine[]> searchDefinitionMap = new HashMap<SearchEntityKey, SearchEntityPropertyDefine[]>();

    private static Map<SearchEntityKey, Map<String, SearchEntityPropertyDefine>> searchDefinitionColumnMap = new HashMap<SearchEntityKey, Map<String, SearchEntityPropertyDefine>>();
	
	public static void register(SearchEntityKey entityKey, SearchEntityPropertyDefine[] definition) {
		if (searchDefinitionMap.containsKey(entityKey)) {
			logger.error("字段定义已存在，将覆盖原有定义：{}", entityKey);
		}
        searchDefinitionMap.put(entityKey, definition);

        Map<String, SearchEntityPropertyDefine> columnMap = new HashMap<String, SearchEntityPropertyDefine>();
        for (SearchEntityPropertyDefine propertyDefine : definition) {
            columnMap.put(propertyDefine.getName(), propertyDefine);
        }
        searchDefinitionColumnMap.put(entityKey, columnMap);
    }

	public static SearchEntityPropertyDefine[] get(SearchEntityKey entityKey) {
		if (!searchDefinitionMap.containsKey(entityKey)) {
			logger.error("字段定义不存在：{}", entityKey);
			return null;
		}
		return searchDefinitionMap.get(entityKey);
	}

    public static SearchEntityPropertyDefine get(SearchEntityKey entityKey, String name) {
        if (!searchDefinitionColumnMap.containsKey(entityKey)) {
            logger.error("字段定义不存在：{}", entityKey);
            return null;
        }
        Map<String, SearchEntityPropertyDefine> columnMap = searchDefinitionColumnMap.get(entityKey);
        return columnMap.get(name);
    }

	static {
		register(SearchEntityKey.LOTTERY_ORDER, PlanOrderSearchDefine.get());
		register(SearchEntityKey.USER_ORDER, PlanOrderSearchDefine.get());
        register(SearchEntityKey.RECORD_RECHARGE, RecordRechargeSearchDefine.get());
	}

    public static String[] getField(SearchEntityKey entityKey) {
        SearchEntityPropertyDefine[] definition = get(entityKey);
        if (definition == null) {
            return null;
        }
        List<String> fieldList = new ArrayList<String>();
        for (SearchEntityPropertyDefine propertyDefine : definition) {
            if (propertyDefine.isDeprecated()) {
                continue;
            }
            fieldList.add(propertyDefine.getName());
        }
        return fieldList.toArray(new String[fieldList.size()]);
    }

    public static Object[] getValue(ISearchEntity searchEntity, boolean archive) throws Exception {
        SearchEntityPropertyDefine[] definition = get(searchEntity.getEntityKey());
        if (definition == null) {
            return null;
        }

        List<Object> valueList = new ArrayList<Object>();

        for (SearchEntityPropertyDefine propertyDefine : definition) {
            // 根据类型定义自动转换成整型数据
            Object property = PropertyUtils.getProperty(searchEntity, propertyDefine.getPropertyName());

            if (property != null) {
                ISearchEntityPropertyConverter converter = null;
                if (archive) {
                    converter = propertyDefine.getArchiveConverter();
                    if (converter == null) {
                        converter = propertyDefine.getConverter();
                    }
                } else {
                    converter = propertyDefine.getConverter();
                }

                if (converter != null) {
                    property = converter.convertToSearch(property);
                }
            }
            valueList.add(property);
        }

        return valueList.toArray(new Object[valueList.size()]);
    }

    /**
     * 将filter中的原始数据类型转换为搜索服务的数据类型
     * @param entityKey
     * @param filter
     */
    public static void convertFilter(SearchEntityKey entityKey, SearchApiRequestFilter filter) throws Exception {
        SearchEntityPropertyDefine[] definition = get(entityKey);
        if (definition == null) {
            return;
        }

        List<SearchApiRequestFilterItem> filterItemList = filter.getFilterItemList();
        for (SearchApiRequestFilterItem filterItem : filterItemList) {
            SearchEntityPropertyDefine propertyDefine = get(entityKey, filterItem.getField());
            if (propertyDefine == null) {
                continue;
            }
            ISearchEntityPropertyConverter converter = propertyDefine.getConverter();
            if (converter != null) {
                filterItem.setValue(converter.convertToSearch(filterItem.getValue()));
            }
        }
    }

    /**
     * 自动根据非null属性生成各种EQUAL条件组成的filter
     * @param searchEntity
     * @param convert
     * @return
     * @throws Exception
     */
    public static SearchApiRequestFilter createFilter(ISearchEntity searchEntity, boolean convert) throws Exception {
        SearchEntityPropertyDefine[] definition = get(searchEntity.getEntityKey());
        if (definition == null) {
            return null;
        }
        SearchApiRequestFilter requestFilter = new SearchApiRequestFilter();
        for (SearchEntityPropertyDefine propertyDefine : definition) {
            Object property = PropertyUtils.getProperty(searchEntity, propertyDefine.getPropertyName());
            if (property == null) {
                continue;
            }
            if (convert) {
                ISearchEntityPropertyConverter converter = propertyDefine.getConverter();
                if (converter != null) {
                    property = converter.convertToSearch(property);
                }
            }
            requestFilter.addEqual(propertyDefine.getName(), property);
        }
        return requestFilter;
    }

    public static void copyProperties(ISearchEntity searchEntity, JSONArray jsonArray, String[] field) throws Exception {
        for (int i = 0; i < field.length; i++) {
            SearchEntityPropertyDefine propertyDefine = get(searchEntity.getEntityKey(), field[i]);

            Object property = null;

            ISearchEntityPropertyConverter converter = propertyDefine.getConverter();
            if (converter == null) {
                property = jsonArray.get(i);
            } else {
                boolean isNull = CoreJSONUtils.isNull(jsonArray.get(i));
                if (!isNull) {
                    property = converter.convertFromSearch(converter.getFromJSON(jsonArray, i));
                }
            }

            PropertyUtils.setProperty(searchEntity, propertyDefine.getPropertyName(), property);
        }
    }
}
